/*
 * This file is part of aion-unique <aion-unique.org>.
 *
 *  aion-unique is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  aion-unique is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with aion-unique.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.aionengine.gameserver.model.gameobjects.player;

import com.aionengine.gameserver.model.gameobjects.Letter;
import com.aionengine.gameserver.model.gameobjects.LetterType;
import com.aionengine.gameserver.network.aion.serverpackets.SM_MAIL_SERVICE;
import com.aionengine.gameserver.services.mail.MailService;
import com.aionengine.gameserver.utils.PacketSendUtility;
import javolution.util.FastMap;

import java.util.*;

/**
 * @author kosyachok
 * @modified Atracer
 */
public class Mailbox {

    private Map<Integer, Letter> mails = new FastMap<Integer, Letter>().shared();
    private Map<Integer, Letter> reserveMail = new FastMap<Integer, Letter>().shared();
    private Player owner;
    public boolean isMailListUpdateRequired;

    // 0x00 - closed
    // 0x01 - regular
    // 0x02 - express
    public byte mailBoxState = 0;

    public Mailbox(Player player) {
        this.owner = player;
    }

    /**
     * @param letter
     */
    public void putLetterToMailbox(Letter letter) {
        if (haveFreeSlots())
            mails.put(letter.getObjectId(), letter);
        else
            reserveMail.put(letter.getObjectId(), letter);
    }

    /**
     * Get all letters in mailbox (sorted according to time received)
     *
     * @return
     */
    public Collection<Letter> getLetters() {
        SortedSet<Letter> letters = new TreeSet<Letter>(new Comparator<Letter>() {

            @Override
            public int compare(Letter o1, Letter o2) {
                if (o1.getTimeStamp().getTime() > o2.getTimeStamp().getTime())
                    return 1;
                if (o1.getTimeStamp().getTime() < o2.getTimeStamp().getTime())
                    return -1;

                return o1.getObjectId() > o2.getObjectId() ? 1 : -1;
            }

        });

        for (Letter letter : mails.values()) {
            letters.add(letter);
        }
        return letters;
    }

    /**
     * Get system letters which senders start with the string specified and were received since the last player login
     *
     * @param substring must start with special characters: % or $$
     * @return new list of letters
     */
    public List<Letter> getNewSystemLetters(String substring) {
        List<Letter> letters = new ArrayList<Letter>();
        for (Letter letter : mails.values()) {
            if (letter.getSenderName() == null || !letter.isUnread())
                continue;
            if (owner.getCommonData().getLastOnline().getTime() > letter.getTimeStamp().getTime())
                continue;
            if (letter.getSenderName().startsWith("%") || letter.getSenderName().startsWith("$$")) {
                if (letter.getSenderName().startsWith(substring))
                    letters.add(letter);
            }
        }
        return letters;
    }

    /**
     * Get letter with specified letter id
     *
     * @param letterObjId
     * @return
     */
    public Letter getLetterFromMailbox(int letterObjId) {
        return mails.get(letterObjId);
    }

    /**
     * Check whether mailbox contains empty letters
     *
     * @return
     */
    public boolean haveUnread() {
        for (Letter letter : mails.values()) {
            if (letter.isUnread())
                return true;
        }
        return false;
    }

    public final int getUnreadCount() {
        int unreadCount = 0;
        for (Letter letter : mails.values()) {
            if (letter.isUnread())
                unreadCount++;
        }
        return unreadCount;
    }

    public boolean haveUnreadByType(LetterType letterType) {
        for (Letter letter : mails.values()) {
            if (letter.isUnread() && letter.getLetterType() == letterType)
                return true;
        }
        return false;
    }

    public final int getUnreadCountByType(LetterType letterType) {
        int count = 0;
        for (Letter letter : mails.values()) {
            if (letter.isUnread() && letter.getLetterType() == letterType)
                count++;
        }
        return count;
    }

    /**
     * @return
     */
    public boolean haveFreeSlots() {
        return mails.size() < 100;
    }

    /**
     * @param letterId
     */
    public void removeLetter(int letterId) {
        mails.remove(letterId);
        uploadReserveLetters();
    }

    /**
     * Current size of mailbox
     *
     * @return
     */
    public int size() {
        return mails.size();
    }

    public void uploadReserveLetters() {
        if (reserveMail.size() > 0 && haveFreeSlots()) {
            for (Letter letter : reserveMail.values()) {
                if (haveFreeSlots()) {
                    mails.put(letter.getObjectId(), letter);
                    reserveMail.remove(letter.getObjectId());
                } else
                    break;
            }
            MailService.getInstance().refreshMail(getOwner());
        }
    }

    public void sendMailList(boolean expressOnly) {
        PacketSendUtility.sendPacket(owner, new SM_MAIL_SERVICE(owner, getLetters(), expressOnly));
    }

    public Player getOwner() {
        return owner;
    }

}
